home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-01-11 | 7.4 KB | 278 lines | [TEXT/CWIE] |
- // TThread.cp - Macintosh Thread class object
- //
- // Apple Macintosh Developer Technical Support
- // Written by: Vinne Moscaritolo
- //
- // Copyright (work in progress) Apple Computer, Inc All rights reserved.
- //
- // You may incorporate this sample code into your applications without
- // restriction, though the sample code has been provided "AS IS" and the
- // responsibility for its operation is 100% yours. However, what you are
- // not permitted to do is to redistribute the source as "DSC Sample Code"
- // after having made changes. If you're going to re-distribute the source,
- // we require that you make it clear in the source that the code was
- // descended from Apple Sample Code, but that you've made changes.
- //
-
-
- #include "TMacException.h"
- #include "TThread.h"
-
- #include "TNetworkException.h"
- #include <strstream.h>
-
- // ===========================================================================
- // Static member variables
- // ===========================================================================
-
- Boolean TThread::fgInited = false; // is Thread class library inited
- ProcessSerialNumber TThread::fgPSN; // application's PSN
- ThreadTaskRef TThread::fgThreadTaskRef; // thread task ref
-
- // ---------------------------------------------------------------------------
- // DoEntry (pascal wrapper function)
- // ---------------------------------------------------------------------------
- // Thread manager Callback for thread entry
-
- pascal void* TThread::DoEntry(void *arg)
- {
- TThread *theThread = (TThread*) arg;
- void* theResult;
-
- // try
- {
- theResult = theThread->Run();
- }
-
- // catch(...)
- {
- // stop error prop
- }
-
- // Recycle thread
- theThread->Stop(theResult);
-
- // cant get here...
- ThrowMsg("TThread :DoEntry returned from dispose");
- return nil;
- }
-
- // ---------------------------------------------------------------------------
- // DoTermination (pascal wrapper function)
- // ---------------------------------------------------------------------------
- // Thread manager Callback for thread termination
-
- pascal void TThread::DoTermination(ThreadID theID, void *arg)
- {
- TThread *theThread = (TThread*) arg;
-
- theThread->fTID = kNoThreadID;
-
- try
- {
- theThread->Done();
- }
- catch(...)
- {
- // all we want is to stop error propagation
- }
- }
-
- // ---------------------------------------------------------------------------
- // DoSwapIn (pascal wrapper function)
- // ---------------------------------------------------------------------------
- // Thread manager Callback for thread Swap in
-
- pascal void TThread::DoSwapIn(ThreadID, void *arg)
- {
- TThread* theThread = (TThread*) arg;
-
- theThread->fContext.Restore();
- }
-
-
- // ---------------------------------------------------------------------------
- // DoSwapOut (pascal wrapper function)
- // ---------------------------------------------------------------------------
- // Thread manager Callback for thread Swap Out
-
- pascal void TThread::DoSwapOut(ThreadID, void *arg)
- {
- TThread *theThread = (TThread*) arg;
-
- theThread->fContext.Save();
- }
-
- // ---------------------------------------------------------------------------
- // TThread
- // ---------------------------------------------------------------------------
- // Default Constructor
-
- TThread::TThread()
- {
- // Check if first time to use thread package
- if (!fgInited) Initialize();
-
- // Set state
- fTID = kNoThreadID;
- }
-
-
- // ---------------------------------------------------------------------------
- // ~TThread
- // ---------------------------------------------------------------------------
- // Destructor
-
- TThread::~TThread()
- {
- // Kill thread if it's running
- Stop(0);
- fTID = kNoThreadID;
- }
-
- // ---------------------------------------------------------------------------
- // Start
- // ---------------------------------------------------------------------------
- // Setup thread for execution
-
- void TThread::Start()
- {
- OSErr ErrNo;
-
- try {
-
- // Create thread
- ThrowIfOSErr (::NewThread( kCooperativeThread, // kCooperativeThread,kPreemptiveThread
- DoEntry, // thread entry proc
- this, // param to entry proc
- 0, // Stack space
- (kReadyThreadState // starting state (ready)
- | kCreateIfNeeded), // try to get from pool
- (void**) &fResult, // place to put quit result
- &fTID)); // place to put task ID
-
- // set terminator and thread switch procs
- ThrowIfOSErr(::SetThreadSwitcher(fTID, DoSwapIn, this, true));
- ThrowIfOSErr(::SetThreadSwitcher(fTID, DoSwapOut, this, false));
- ThrowIfOSErr(::SetThreadTerminator(fTID, DoTermination, this));
- }
- catch(...){
- if (fTID != kNoThreadID) {
- ::SetThreadTerminator(fTID, nil, nil);
- ::DisposeThread(fTID, nil, true);
- fTID = kNoThreadID;
- }
- throw;
- }
- }
-
- // ---------------------------------------------------------------------------
- // Stop
- // ---------------------------------------------------------------------------
- // Stop thread execution
-
- void TThread::Stop(void * theResult)
- {
-
- if(fTID != kNoThreadID){
- ThreadID ourThread = fTID;
- fTID = kNoThreadID; // this might be the last thing this thread does
- ::DisposeThread(ourThread,theResult, true); // so juggle the Tid
- };
- }
-
- // ---------------------------------------------------------------------------
- // Sleep
- // ---------------------------------------------------------------------------
- // Sleep Thread
-
- void TThread::Sleep()
- {
- if(fTID != kNoThreadID)
- ThrowIfOSErr(::SetThreadState(fTID,kStoppedThreadState,kCurrentThreadID));
- }
-
-
- // ---------------------------------------------------------------------------
- // WakeUp
- // ---------------------------------------------------------------------------
- // Wake up Thread
-
- void TThread::WakeUp()
- {
- ThreadState threadState;
-
- if( (fTID != kNoThreadID)
- && (::GetThreadStateGivenTaskRef(fgThreadTaskRef, fTID,&threadState) != noErr)
- && (threadState == kStoppedThreadState))
- ::SetThreadReadyGivenTaskRef(fgThreadTaskRef, fTID);
- }
-
-
- // ---------------------------------------------------------------------------
- // Yield
- // ---------------------------------------------------------------------------
- // Yield time to next thread
-
- void TThread::Yield()
- {
- ::YieldToAnyThread();
- }
-
-
- // ---------------------------------------------------------------------------
- // Run
- // ---------------------------------------------------------------------------
- // default thread Run
-
- void* TThread::Run()
- {
- while(true) {
- Yield();
- }
- return nil;
- }
-
- // ---------------------------------------------------------------------------
- // Done
- // ---------------------------------------------------------------------------
- // default thread Done
-
- void TThread::Done()
- {
- }
-
-
-
- // ---------------------------------------------------------------------------
- // Allocate (static public)
- // ---------------------------------------------------------------------------
- // Allocate memory for Thread manager
-
- void TThread::Allocate(short numToCreate, Size stackSize)
- {
- ThrowIfOSErr(::CreateThreadPool(kCooperativeThread, numToCreate, stackSize));
- }
-
-
- // ---------------------------------------------------------------------------
- // Initialize
- // ---------------------------------------------------------------------------
- // Will run when first thread is started
-
- void TThread::Initialize()
- {
- // is the Thread Manager running ?
- /* if (!UEnvironment::HasFeature(env_HasThreadsManager))
- {
- ThrowOSErr_(threadProtocolErr);
- }
- */
- // low-level initialisation
- ThrowIfOSErr( ::GetCurrentProcess(&fgPSN));
- ThrowIfOSErr( ::GetThreadCurrentTaskRef(&fgThreadTaskRef));
-
- fgInited = true;
- }
-
-